﻿using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace Urs.Core
{
    public class ApiResponse
    {
        /// <summary>
        /// 编号 200:成功,250:警告提示,301:跳转新地址,400:错误请求,404:找不到
        /// </summary>
        public int Code { get; set; }
        /// <summary>
        /// 警告信息或跳转地址
        /// </summary>
        public string Content { get; set; }

        public static ApiResponse Success()
        {
            return new ApiResponse() { Code = 200, Content = "请求成功！" };
        }
        public static ApiResponse Warn(string message)
        {
            return new ApiResponse() { Code = 250, Content = message };
        }
        public static ApiResponse Redirect(string url)
        {
            return new ApiResponse() { Code = 301, Content = url };
        }
        public static ApiResponse BadRequest(string message = null)
        {
            return new ApiResponse() { Code = 400, Content = message };
        }
        public static ApiResponse Disable()
        {
            return new ApiResponse() { Code = 403, Content = "module not open" };
        }
        public static ApiResponse NotFound()
        {
            return new ApiResponse() { Code = 404, Content = "not found" };
        }
    }

    public class ApiResponse<T> : ApiResponse where T : new()
    {
        /// <summary>
        /// 数据对象
        /// </summary>
        public T Data { get; set; }
        public static ApiResponse<T> Success(T data)
        {
            return new ApiResponse<T>() { Code = 200, Content = "请求成功！", Data = S(data) };
        }
        public static ApiResponse<T> Warn(string message)
        {
            return new ApiResponse<T>() { Code = 250, Content = message };
        }
        public static ApiResponse<T> Redirect(string url)
        {
            return new ApiResponse<T>() { Code = 301, Content = url };
        }
        public static ApiResponse<T> BadRequest(string message = null)
        {
            return new ApiResponse<T>() { Code = 400, Content = message };
        }
        public static ApiResponse<T> Disable()
        {
            return new ApiResponse<T>() { Code = 403, Content = "module not open" };
        }
        public static ApiResponse<T> NotFound()
        {
            return new ApiResponse<T>() { Code = 404, Content = "not found" };
        }

        private static T S(T data)
        {
            var settings = new JsonSerializerSettings()
            {
                ContractResolver = new NullToEmptyStringResolver(),
                NullValueHandling = NullValueHandling.Ignore,
                DateFormatString = "yyyy-MM-dd HH:mm"
            };
            var json = JsonConvert.SerializeObject(data, Newtonsoft.Json.Formatting.Indented, settings);
            var obj = JsonConvert.DeserializeObject<T>(json);

            return obj;
        }

        private class NullToEmptyStringResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
        {
            protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
            {
                return type.GetProperties()
                        .Select(p =>
                        {
                            var jp = base.CreateProperty(p, memberSerialization);
                            jp.ValueProvider = new NullToEmptyStringValueProvider(p);
                            return jp;
                        }).ToList();
            }
        }

        private class NullToEmptyStringValueProvider : Newtonsoft.Json.Serialization.IValueProvider
        {
            PropertyInfo _MemberInfo;
            public NullToEmptyStringValueProvider(PropertyInfo memberInfo)
            {
                _MemberInfo = memberInfo;
            }

            public object GetValue(object target)
            {
                object result = _MemberInfo.GetValue(target);
                if (result == null)
                {
                    if (_MemberInfo.PropertyType == typeof(Int32?) || _MemberInfo.PropertyType == typeof(Int64?))
                        result = 0;
                    else if (_MemberInfo.PropertyType != typeof(DateTime?))
                        result = "";
                }
                return result;

            }

            public void SetValue(object target, object value)
            {
                _MemberInfo.SetValue(target, value);
            }
        }
    }
}